package com.shoulder.boot.acl.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shoulder.boot.acl.dto.ClientAddDTO;
import com.shoulder.boot.acl.dto.ClientModDTO;
import com.shoulder.boot.acl.dto.ClientQueryDTO;
import com.shoulder.boot.acl.entity.Oauth2RegisteredClient;
import com.shoulder.boot.acl.exception.AclException;
import com.shoulder.boot.acl.mapper.ClientMapper;
import com.shoulder.boot.acl.service.ClientService;
import com.shoulder.boot.acl.utils.ClientUtils;
import com.shoulder.boot.acl.vo.ClientVo;
import com.shoulder.core.fetch.BaseIds;
import lombok.AllArgsConstructor;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.settings.ClientSettings;
import org.springframework.security.oauth2.server.authorization.settings.TokenSettings;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.time.Duration;
import java.util.Collections;
import java.util.List;
import java.util.UUID;

/**
 * 客户端信息 服务实现类
 *
 * @author 596767880@qq.com
 * @since 2025-09-02 10:40:32
 */
@Service
@AllArgsConstructor
public class ClientServiceImpl extends ServiceImpl<ClientMapper, Oauth2RegisteredClient> implements ClientService {

    private final PasswordEncoder passwordEncoder;
    private final RegisteredClientRepository clientRepository;
    private final JdbcTemplate jdbcTemplate;

    @Override
    public void add(ClientAddDTO addDTO) {
        RegisteredClient registeredClient = clientRepository.findByClientId(addDTO.getClientId());
        if (registeredClient != null) {
            throw new AclException("客户端已存在");
        }

        RegisteredClient.Builder clientBuilder = RegisteredClient.withId(IdWorker.getIdStr())
                .clientId(addDTO.getClientId())
                .clientName(addDTO.getClientId())
                .clientSecret(passwordEncoder.encode(addDTO.getClientSecret()));


        //客户端认证方式
        addDTO.getClientAuthenticationMethods().forEach(clientAuthenticationMethod
                -> clientBuilder.clientAuthenticationMethod(new ClientAuthenticationMethod(clientAuthenticationMethod)));


        //授权方式
        addDTO.getAuthorizationGrantTypes().forEach(authorizationGrantType
                -> clientBuilder.authorizationGrantType(new AuthorizationGrantType(authorizationGrantType)));

        clientBuilder.redirectUri(addDTO.getRedirectUri());

        for (String s : addDTO.getScopes().split(",")) {
            clientBuilder.scope(s);
        }

        clientBuilder.clientSettings(ClientSettings.builder().requireAuthorizationConsent(addDTO.getRequireAuthorizationConsent()).build());

        clientBuilder.tokenSettings(TokenSettings.builder()
                .refreshTokenTimeToLive(Duration.ofSeconds(addDTO.getRefreshTokenValidTime()))
                .accessTokenTimeToLive(Duration.ofSeconds(addDTO.getTokenValidTime())).build());


        clientRepository.save(clientBuilder.build());
    }

    @Override
    public void mod(ClientModDTO modDTO) {

        this.baseMapper.delete(new LambdaQueryWrapper<Oauth2RegisteredClient>().eq(Oauth2RegisteredClient::getClientId, modDTO.getClientId()));
        add(modDTO);

    }

    @Override
    public Page<ClientVo> pageQuery(ClientQueryDTO queryDTO) {
        Page<Oauth2RegisteredClient> selectPage = this.baseMapper.selectPage(new Page<>(queryDTO.getCurrent(), queryDTO.getSize())
                , ClientUtils.buildQueryWrapper(queryDTO));
        if (selectPage == null || CollectionUtils.isEmpty(selectPage.getRecords())) {
            return new Page<>();
        }
        return ClientUtils.buildUtils().toPage(selectPage);
    }

    @Override
    public List<ClientVo> listQuery(ClientQueryDTO queryDTO) {
        List<Oauth2RegisteredClient> list = this.baseMapper.selectList(ClientUtils.buildQueryWrapper(queryDTO));
        if (CollectionUtils.isEmpty(list)) {
            return Collections.emptyList();
        }
        return ClientUtils.buildUtils().toVos(list);
    }

    @Override
    public void batchDel(BaseIds<String> baseIds) {

        this.baseMapper.delete(new LambdaQueryWrapper<Oauth2RegisteredClient>().in(Oauth2RegisteredClient::getId, baseIds.getIds()));
    }

    @Override
    public void del(String id) {
        Oauth2RegisteredClient entity = this.baseMapper.selectById(id);
        if (ObjectUtils.isEmpty(entity)) {
            throw new AclException("客户端信息不存在");
        }
        this.baseMapper.deleteById(id);
    }


    @Override
    public ClientVo look(String id) {
        Oauth2RegisteredClient entity = this.baseMapper.selectById(id);
        if (ObjectUtils.isEmpty(entity)) {
            throw new AclException("客户端信息不存在");
        }
        return ClientUtils.buildUtils().toVo(entity);
    }
}
